package com.syygl.chase.core;


import com.syygl.chase.annotation.NeedLoadedDataTag;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.concurrent.CompletableFuture;

@Aspect
@Service
public class NeedLoadedDataAspect {

    @Autowired
    SpringReflectUtils springReflectUtils;

    public NeedLoadedDataAspect() {
    }

    @Pointcut("@annotation(com.syygl.chase.annotation.NeedLoadedDataTag)")
    public void needLoadedDataAspectPointCut() {
    }

    @Around(value = "needLoadedDataAspectPointCut()")
    public Object aroundNeedLoadedDataMethod(ProceedingJoinPoint joinPoint) throws Throwable {
        Object obj = null;
        try {

            //获取方法上的注解
            NeedLoadedDataTag needLoadedDataTag = ((MethodSignature) joinPoint.getSignature()).getMethod().getAnnotation(NeedLoadedDataTag.class);
            //被注解标注方法上的入参
            Object[] args = joinPoint.getArgs();
            //需要串行准备的数据
            String[] serialPrepareDatas = needLoadedDataTag.serialPrepareData();
            if (null != serialPrepareDatas && serialPrepareDatas.length > 0) {
                Arrays.stream(serialPrepareDatas).forEach(s -> {
                    String[] split = s.split("#");
                    try {
                        Object o = springReflectUtils.invokeMethod(split[0], split[1], args);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                });
            }

            //需要并行准备的数据
            String[] parallelPrepareDatas = needLoadedDataTag.parallelPrepareData();
            if (null != parallelPrepareDatas && parallelPrepareDatas.length > 0) {
                CompletableFuture[] array = new CompletableFuture[parallelPrepareDatas.length];
                for (int i = 0; i < parallelPrepareDatas.length; i++) {
                    String[] split = parallelPrepareDatas[i].split("#");
                    CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {
                        try {
                            Object o = springReflectUtils.invokeMethod(split[0], split[1], args);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        return "success";
                    });
                    array[i] = completableFuture;
                }
                CompletableFuture.allOf(array);//等待所有异步任务结束
            }

            obj = joinPoint.proceed();
        } catch (Exception e) {

        } finally {

        }
        return obj;
    }


}
